package de.tum.in.far.threedui.superbrickball.gui;

import java.util.Hashtable;
import java.util.Map;

import javax.media.j3d.Appearance;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Vector3f;

import de.tum.in.far.threedui.general.BackgroundObject;
import de.tum.in.far.threedui.general.BinaryEnv;
import de.tum.in.far.threedui.general.ImageReceiver;
import de.tum.in.far.threedui.general.ObservablePoseReceiver;
import de.tum.in.far.threedui.general.PoseListener;
import de.tum.in.far.threedui.general.UbitrackFacade;
import de.tum.in.far.threedui.general.ViewerUbitrack;
import de.tum.in.far.threedui.superbrickball.engine.physics.World;

public class SuperBallGameGUI implements SuperBallGame {

	TransformGroup ballTG;
	TransformGroup controllerTG;
	Map<String, TransformGroup> brickTGs;
	Appearance brickAppearance;
	Appearance wallAppearance;
	Appearance ballAppearance;
	Appearance controllerAppearance;

	float ballRadius;

	TransformGroup mainTransform;
	TransformGroup controllerRectifierTransform;

	static {
		BinaryEnv.init();
	}

	private ViewerUbitrack viewer;
	private UbitrackFacade ubitrackFacade;

	ObservablePoseReceiver poseReceiver;
	BackgroundObject backgroundObject;
	ImageReceiver imageReceiver;
	PoseListener poseListener;

	World world;
	
	public SuperBallGameGUI(PoseListener poseListener, World world) {
		this.world = world;
		this.poseListener = poseListener;
		brickTGs = new Hashtable<>();
		brickAppearance = new CustomAppearance(.5f, 0, 0, .31f);
		wallAppearance = new CustomAppearance("textures/wood-texture.jpg");
		ballAppearance = new CustomAppearance(0, .5f, .5f);
		controllerAppearance = new CustomAppearance(0, .5f, 0, 0.21f);
		
		
		ballRadius = world.ballRadius;


		Transform3D mainTransform3D = new Transform3D();

		this.mainTransform = new TransformGroup(mainTransform3D);
		this.mainTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		this.mainTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		this.mainTransform.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);

		Transform3D controllerRectififierTransform3D = new Transform3D();
		controllerRectififierTransform3D.rotY(Math.PI * 1f);
		controllerRectififierTransform3D.setTranslation(new Vector3f(0, 0, -1.17f));

		this.controllerRectifierTransform= new TransformGroup(controllerRectififierTransform3D);
		this.controllerRectifierTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		this.controllerRectifierTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		this.controllerRectifierTransform.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
		this.mainTransform.addChild(controllerRectifierTransform);

		SphereObject ball = new SphereObject(this.ballRadius, this.ballAppearance);
		this.ballTG = ball.getTransformGroup();
		this.mainTransform.addChild(ball);
		
		
		CubeObject controller = new CubeObject(world.controllerDimension, world.controllerDimension, 0.001f,
				controllerAppearance);
		controllerTG = controller.getTransformGroup();
		this.controllerRectifierTransform.addChild(controller);

		ubitrackFacade = new UbitrackFacade();
		viewer = new ViewerUbitrack("Super Brick Ball !!", ubitrackFacade);
		initializeUbitrack();

		viewer.addObject(this.mainTransform);

	}

	private void initializeUbitrack() {

		// poseReceiver.
		ubitrackFacade.initUbitrack();

		// ubitrackFacade.
		poseReceiver = new ObservablePoseReceiver("CONTROLLER"){
			@Override
			public Transform3D getTransform3D() {
//				Vector3f ball = new Vector3f();
//				Transform3D temp = new Transform3D();
//				ballTG.getTransform(temp);
//				temp.get(ball);
//				
//				Vector3f board = new Vector3f();
//				temp = getControllerTransform();
//				temp.get(board);
//				
//				viewer.addObject(new VanishingLine(new Point3f(board), new Point3f(ball)));
				return getControllerTransform();
			}
		};
		poseReceiver.addPoseListener(poseListener);
		
		if (!ubitrackFacade.setPoseCallback("posesink", poseReceiver)) {
			return;
		}

		imageReceiver = new ImageReceiver();
		if (!ubitrackFacade.setImageCallback("imgsink", imageReceiver)) {
			return;
		}

		backgroundObject = new BackgroundObject();
		// viewer.addObject(backgroundObject);
		// imageReceiver.setBackground(backgroundObject.getBackground());

		poseReceiver.setTransformGroup(this.controllerTG);

		ubitrackFacade.startDataflow();
	}

	@Override
	public Transform3D getBallTransform() {
		Transform3D t3d = new Transform3D();
		this.ballTG.getTransform(t3d);
		return t3d;
	}

	@Override
	public Transform3D getControllerTransform() {
		Transform3D controllerT3D = new Transform3D();
		this.controllerTG.getTransform(controllerT3D);

		// Vector3f controllerTranslation = new Vector3f();
		// Quat4f controllerRotation = new Quat4f();
		// controllerT3D.get(controllerTranslation);
		// controllerT3D.get(controllerRotation);

		Transform3D mainT3D = new Transform3D();
		this.mainTransform.getTransform(mainT3D);
		

		Transform3D rectifierT3D = new Transform3D();
		this.controllerRectifierTransform.getTransform(rectifierT3D);
		// mainT3D.transform(controllerTranslation);
		// mainT3D.transform
		// mainT3D.transform(controllerRotation);
		// Transform3D resultT3D = new Transform3D();
		// resultT3D.set(controllerRotation);
		// resultT3D.set(controllerTranslation);

		rectifierT3D.mul(controllerT3D);
		mainT3D.mul(rectifierT3D);
		return mainT3D;
	}

	@Override
	public void addSphericalBrick(String id, Transform3D center, float radius) {

		System.out.println("BRICK ID :" + id);
		SphereObject brick = new SphereObject(radius, this.brickAppearance);
		this.brickTGs.put(id, brick.getTransformGroup());
		brick.getTransformGroup().setTransform(center);

		this.mainTransform.addChild(brick);
	}

	@Override
	public void addWall(Transform3D center, float xDim, float yDim, float zDim) {

		CubeObject wall = new CubeObject(xDim, yDim, zDim, this.wallAppearance);
		wall.getTransformGroup().setTransform(center);
		this.mainTransform.addChild(wall);

	}

	@Override
	public void setBallTransform(Transform3D newBallTransform) {
		this.ballTG.setTransform(newBallTransform);
	}

	@Override
	public void destroyBrick(String brickID) {
		 TransformGroup target = this.brickTGs.get(brickID);
		 Transform3D invisible = new Transform3D();
		 invisible.setTranslation(new Vector3f(0,0,1000));
		 target.setTransform(invisible);
//		 target.removeAllChildren();
		 this.brickTGs.remove(brickID);
	}

	@Override
	public void endGame(boolean gamesStatus) {
		for(int i = 0 ; i < 10000 ; i ++)
			System.err.print("GAME ENDED :" + gamesStatus);

	}

}
